package com.sdlh.demo.compress;

import com.github.luben.zstd.Zstd;
import com.github.luben.zstd.ZstdInputStream;
import com.github.luben.zstd.ZstdOutputStream;
import lombok.extern.slf4j.Slf4j;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;

@Slf4j
public class ZstdDemo {
    private static final String DATA_PATH = "D:\\workspace\\井上采集数据\\";

    public static void main(String[] args) {
        testZstd();
    }

    private static void deleteIfExists(String filePath) {
        try {
            Files.deleteIfExists(Path.of(filePath));
        } catch (IOException e) {
            log.error("删除文件失败", e);
        }
    }

    private static void testZstd() {
        String input = DATA_PATH + "12345679.DAT";
        String output = DATA_PATH + "12345679.DAT.zstd";
        deleteIfExists(output);
        long start = System.currentTimeMillis();
        zstdCompress(input, output);
        log.info("zstd压缩文件耗时" + (System.currentTimeMillis() - start) + "ms");
        start = System.currentTimeMillis();
        zstdDecompress(output, DATA_PATH + "12345679.DAT.bak");
        log.info("zstd解压缩文件耗时" + (System.currentTimeMillis() - start) + "ms");
    }

    private static void zstdCompress(String input, String output) {
        try(FileChannel inputChannel = new RandomAccessFile(input, "r").getChannel();
            FileChannel outputChannel = new RandomAccessFile(output, "rw").getChannel()) {
            ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 50);
            while (inputChannel.read(buffer) > 0) {
                buffer.flip();
                ByteBuffer compress = Zstd.compress(buffer, 8);
                buffer.clear();
                outputChannel.write(compress);
            }
        } catch (Exception e) {
            log.error("zstd压缩文件失败", e);
        }
    }

    private static void zstdCompress2(String input, String output) {
        try(FileInputStream inputStream = new FileInputStream(input);
            ZstdOutputStream outputStream = new ZstdOutputStream(new FileOutputStream(output)).setLevel(8)) {
            byte[] buffer = new byte[1024 * 1024 * 50];
            int read;
            while (true) {
                read = inputStream.read(buffer);
                if (read < 0) break;
                outputStream.write(buffer, 0, read);
            }
        } catch (Exception e) {
            log.error("zstd压缩文件失败", e);
        }
    }

    private static void zstdDecompress(String input, String output) {
        try(
                FileChannel writeChannel = new RandomAccessFile(output, "rw").getChannel();
                ZstdInputStream zstdInputStream = new ZstdInputStream(new FileInputStream(input))) {
            byte[] decodebuffer = new byte[1024 * 1024 * 50];
            int read;

            while (true) {
                read = zstdInputStream.read(decodebuffer);

                if (read <= 0) {
                    break;
                } else {
                    writeChannel.write(ByteBuffer.wrap(decodebuffer, 0, read));
                }
            }

        } catch (Exception e) {
            log.error("zstd解压缩文件失败", e);
        }
    }
}
